package m.system.task;

import m.system.cache.run.CacheHostTask;
import m.system.db.TransactionManager;
import m.system.util.AnnotationUtil;
import m.system.util.ClassUtil;
import m.system.util.SystemUtil;

import java.util.*;

public class TaskUtil {
	private static final Timer timer=new Timer();
	private static final Map<String,Boolean> runnableMap=new HashMap<>();
	private static final Map<Class<?>,Map<String,TaskStartRunMeta>> startRunMap=new HashMap<>();
	private static final Map<String,Long> startNextRunMap=new HashMap<>();
	private static final Map<Class<?>,Map<String,TaskTimerRunMeta>> timerRunMap=new HashMap<>();
	private static String key(Class<?> clazz,String method){
		return clazz.getName()+":"+method;
	}
	public static void initTask(List<String> list) throws  ClassNotFoundException {
		List<Class<?>> classList=new ArrayList<>();
		classList.add(CacheHostTask.class);
		classList.add(SystemTask.class);
		for(String clazz : list){
			classList.add(ClassUtil.getClass(clazz));
		}
		for(Class<?> clazz : classList){
			Map<String,TaskStartRunMeta> sMap=AnnotationUtil.getAnnotationMap4Method(TaskStartRunMeta.class,clazz);
			if(!sMap.isEmpty()) {
				startRunMap.put(clazz, sMap);
				sMap.keySet().forEach(key -> {
					startNextRunMap.put(key(clazz, key), 0L);
					runnableMap.put(key(clazz, key), true);
				});
			}
			Map<String,TaskTimerRunMeta> tMap=AnnotationUtil.getAnnotationMap4Method(TaskTimerRunMeta.class,clazz);
			if(!tMap.isEmpty()) {
				timerRunMap.put(clazz, tMap);
				tMap.keySet().forEach(key -> {
					runnableMap.put(key(clazz, key), true);
				});
			}
		}
		timer.schedule(new TimerTask() {
			@Override
			public void run() {
				Date time=new Date();
				//初始化间隔定时器
				startRunMap.forEach((clazz,map)->{
					map.forEach((method,meta)->{
						String key=key(clazz,method);
						Long nextTime=startNextRunMap.get(key);
						if(runnableMap.get(key)&&nextTime<time.getTime()){
							new Thread(()->{
								if(meta.init()&&nextTime==0L//首次执行
									||meta.interval()>0&&nextTime!=0L) {//间隔执行
									runMethod(clazz, method, key);
								}
								if(meta.interval()>0) {//有间隔执行，设置下次时间
									startNextRunMap.put(key, time.getTime() + meta.interval() * 1000L);
								}else{//无间隔，设置最大
									startNextRunMap.put(key, Long.MAX_VALUE);
								}
								TransactionManager.closeConnection();
							}).start();
						}
					});
				});
				//年月日时分秒定时器
				timerRunMap.forEach((clazz,map)->{
					map.forEach((method,meta)->{
						String key=key(clazz,method);
						if(runnableMap.get(key)){
							Calendar cal=Calendar.getInstance();
							cal.setTime(time);
							if(meet(meta.year(),cal.get(Calendar.YEAR))
									&&meet(meta.month(),cal.get(Calendar.MONTH)+1)
									&&meet(meta.day(),cal.get(Calendar.DAY_OF_MONTH))
									&&meet(meta.hour(),cal.get(Calendar.HOUR_OF_DAY))
									&&meet(meta.minute(),cal.get(Calendar.MINUTE))
									&&meet(meta.second(),cal.get(Calendar.SECOND))
									&&meet(meta.week(),cal.get(Calendar.DAY_OF_WEEK)-1)){
								new Thread(()->{
									runMethod(clazz, method, key);
									TransactionManager.closeConnection();
								}).start();
							}
						}
					});
				});
			}
			private boolean meet(int[] ns,int n){
				if(ns.length==0) return true;//数组为空满足条件
				for(int i : ns){
					if(i==n) return true;
				}
				return false;
			}
			private void runMethod(Class<?> clazz,String method,String key){
				runnableMap.put(key,false);
				try{
					ClassUtil.executeMethod(ClassUtil.newInstance(clazz),method);
				}catch (Exception e){
					SystemUtil.printErr("定时器执行异常",key,"; ",e.getMessage());
					e.printStackTrace();
				}finally {
					runnableMap.put(key,true);
				}
			}
		},0,1000);
		SystemUtil.printlnIf(true,"任务已初始化完毕!");
	}
	public static void closeTask(){
		timer.cancel();
	}

}
